import numpy as np
import math
from PIL import Image
# from .Helper import CropImage

import os
import copy
class CImage:
    
    wsize   = 800    #截取子图片大小
    fixlap  = 150   #重叠图片之间像素大小
    # limSize = (3725, 5025)  #不用放缩的图片大小
    # reSize  = (4050, 4700)   #放缩的图片
    limSize = (3075, 5025)   #不用放缩的图片大小
    reSize  = (3400, 4700)   #放缩的图片

    ratioW = 1.0
    ratioH = 1.0
    offset = [0, 0]

    def __init__(self, fileName, isCrop=False, szImage=(-1, -1), isSaveResizeImage=True): ## isCrop 是否crop图，2023-03-23
        self.img = Image.open(fileName)
        # print('CImage(init):', self.img.size)

        self.imageHeight = self.img.height #self.img.size[1]
        self.imageWidth  = self.img.width  #self.img.size[0]
        self.imagePath   = fileName

        self.orginHeight = self.imageHeight
        self.orginWidth = self.imageWidth

        # print('图片尺寸比较：', szImage)
        if szImage[0] != self.imageWidth and szImage[0] > 0:##2023-06-03 需要旋转90度
            self.img = self.img.transpose(Image.ROTATE_270)
            self.imageHeight = self.img.height
            self.imageWidth = self.img.width
            print('....做了图片旋转:', szImage, self.imageWidth)



        self.resizeImg(isCrop, isSaveResizeImage)##重置图片
    ##

    ##缩放图片在指定范围内
    def resizeImg(self, isCrop, isSaveResizeImage=True):
        maxSize = max(self.imageHeight, self.imageWidth)

        if maxSize <= CImage.limSize[1] and maxSize >= CImage.limSize[0]:##表明不需要放缩
            ## 2023-03-22 ##########################################
            off, newSize, isCut = self.getOffset(isCrop, self.imageHeight, self.imageWidth)
            self.offset = off
            if isCut:##需要剪裁
                img = self.img.crop((off[0], off[1], off[0] + newSize[0], off[1] + newSize[1]))

                if isSaveResizeImage == True:
                    img.save(self.imagePath)      # 覆盖原来的图片

                self.img = img
                self.imageWidth = newSize[0]
                self.imageHeight = newSize[1] #ratio 不变
            return
            ##########################################################

        print('CImage:resizeImg:', maxSize)##下面需要放缩
        ## 超出尺寸要缩放
        ratio = 1.0
        if maxSize > CImage.limSize[1]:
            ratio = CImage.reSize[1] / maxSize
        elif maxSize < CImage.limSize[0]:
            ratio = CImage.reSize[0] /maxSize

        ww = round(self.imageWidth * ratio)
        hh = round(self.imageHeight * ratio)

        img = self.img.resize((ww, hh))
        self.ratioW = ww / self.imageWidth  #保存原始比例
        self.ratioH = hh / self.imageHeight

        ## 2023-03-22 ###################################################
        off, newSize, isCut = self.getOffset(isCrop, hh, ww)
        self.offset = off
        if isCut:
            img = self.img.crop((off[0], off[1], off[0] + newSize[0], off[1] + newSize[1]))
            ww, hh = newSize
        ##################################################################
        if isSaveResizeImage == True:
            img.save(self.imagePath)            #覆盖原来的图片

        self.img = img

        self.imageWidth = ww
        self.imageHeight = hh               #重新设置新的图片大小与路径，

    ## 2023-03-22 增加截取边界的计算
    def getOffset(self, isCrop, hh, ww):
        if isCrop == False:
            return [0, 0], [ww, hh], False
        # if ww == hh:
        #     return
        wsize = CImage.wsize
        space = CImage.wsize - CImage.fixlap
        freeLap = CImage.fixlap * 2 / 3
        nnW = ((ww - wsize) // space) * space + wsize
        nnH = ((hh - wsize) // space) * space + wsize

        if nnH < nnW:
            nLeft = math.floor((ww - nnW)/2)
            nTop = 0
            isCut = nnW != ww
            ww2 = nnW
            hh2 = hh

            if nnH + freeLap > hh:
                nTop = math.floor((hh - nnH)/2)
                isCut |= nnH != hh
                hh2 = nnH
        else:
            nLeft = 0
            nTop = math.floor((hh - nnH)/2)
            isCut = nnH != hh
            hh2 = nnH
            ww2 = ww

            if nnW + freeLap > ww:
                nTop = math.floor((ww - nnW)/2)
                isCut |= nnW != ww
                ww2 = nnW

        return [nLeft, nTop], [ww2, hh2], isCut


    ## 获取每个子图片的区域范围
    def getPatchGridEx(self):
        fixlap  = CImage.fixlap
        wsize   = CImage.wsize

        szImage = [self.imageWidth, self.imageHeight]
        overlap = [fixlap, fixlap]
        # print(wsize, overlap)
        wwSize  = [wsize - fixlap] * 2

        cols    = range(0, szImage[0] - fixlap, wwSize[0])
        rows    = range(0, szImage[1] - fixlap, wwSize[1])

        nTimes  = (len(cols), len(rows))
        # print('CImage(getPatchGridEx),nTimes:', nTimes, cols, rows)

        boxes   = []

        for top in rows:
            for left in cols:
                box = [left, top, left + wsize-1, top + wsize-1]
                boxes.append(box)

        # print('子图的boxes：', boxes)
        nums  = len(boxes)

        self.boxes = boxes
        self.overlaps = overlap
        self.columns = nTimes[0]
        self.nums = nums
        return boxes, overlap, nTimes[0], nums


    def segImagePieces(self, json_src, img, savepath, isSaveJson=True):
        boxes = self.boxes ##子图范围
        ww = self.wsize
        overlap = self.overlaps
        columns = self.columns

        [save_seg_json_dir, save_seg_img_dir, fileName] = savepath
        [_, fName]    = os.path.split(fileName)
        [pureName, _] = os.path.splitext(fName)

        json_temp = copy.deepcopy(json_src)
        json_temp.json_data['imageData'] = None
        json_temp.json_data['imageHeight'] = ww
        json_temp.json_data['imageWidth'] = ww

        # json_obj = copy.copy(json_src)

        print('CImage(segImagePieces):', boxes)
        for i in range(len(boxes)):
            # print('子图第几个：', i)

            rect = boxes[i]
            # img_sub = CropImage(img, rect, ww);
            # print('截取尺寸：', rect)
            # img_sub = img.crop(rect)
            img_sub = CImage.cropImage(img, rect)

            fileNo = pureName + '_' + CImage.getString(i, columns)

            JsonName = os.path.join(save_seg_json_dir, fileNo + '.json')
            ImgName = os.path.join(save_seg_img_dir, fileNo + '.jpg')

            shapes = json_src.getShapesInRect(rect, overlap)
            # print('segImagePieces:', shapes)
            json_temp.json_data['shapes'] = shapes
            json_temp.setAttachedData(rect, overlap)

            json_temp.encodeImageData(img_sub, ImgName, True)

            if isSaveJson == True:
                json_temp.saveJsonFile(JsonName)

    ## 只分割图片，不分割JSON
    def segImagePieces2(self, savepath, isSaveFiles=True):
        img = self.img
        boxes = self.boxes ##子图范围
        ww = self.wsize
        overlap = self.overlaps
        columns = self.columns

        [_, save_seg_img_dir, fileName] = savepath
        [_, fName]    = os.path.split(fileName)
        [pureName, _] = os.path.splitext(fName)

        listSubImages = []
        # print('CImage(segImagePieces2):', boxes)
        for i in range(len(boxes)):
            rect = boxes[i]

            img_sub = CImage.cropImage(img, rect)

            if isSaveFiles == True:  ## 保存子图到文件
                fileNo = pureName + '_' + CImage.getString(i, columns)
                ImgName = os.path.join(save_seg_img_dir, fileNo + '.jpg')
                img_sub.save(ImgName, format="JPEG", quality=90)
                # img_sub.save(ImgName)# 2023-04-25 采用默认的quality保存与quality=90的检测结果不一样，如seed(6).jpg
            else:
                listSubImages.append(img_sub)

        ##self.listSubImages = listSubImages  ##应该不需要保存位成员变量
        return listSubImages ##2022-10-15 增加只保存内存，不保存文件的做法

    @staticmethod
    def getString(kk, cols):
        row = math.floor(kk / cols) + 1
        col = kk %  cols + 1
        ret = '(%d,%d)' % (row, col)
        return ret

    @staticmethod
    def cropImage(img, rect):
        return img.crop([rect[0], rect[1], rect[2] + 1, rect[3] + 1])



##############################################################################################################

if __name__ == "__main__":
    dirSavePath = r'K:\tmp'

    import shutil
    import matplotlib.pyplot as plt
    import cv2

    # fileFullImage = r'F:\玉溪烟草\seed\seed(1).jpg'
    #
    # [_, fName] = os.path.split(fileFullImage)
    # fileCopyPath = os.path.join(dirSavePath, fName)
    # shutil.copyfile(fileFullImage, fileCopyPath)
    # obj = CImage(fileCopyPath)
    # plt.imshow(obj.img)
    #
    # cv2.waitKey(20)

    fileFullImage = r'F:\UAV\2017-10-27\JPG\CSV000019.JPG'
    [_, fName] = os.path.split(fileFullImage)
    fileCopyPath = os.path.join(dirSavePath, fName)
    shutil.copyfile(fileFullImage, fileCopyPath)
    obj = CImage(fileCopyPath)
    plt.imshow(obj.img)

    cv2.waitKey(20)

    fileFullImage = r'G:\四正三角正面1.8.jpg'
    [_, fName] = os.path.split(fileFullImage)
    fileCopyPath = os.path.join(dirSavePath, fName)
    shutil.copyfile(fileFullImage, fileCopyPath)
    obj = CImage(fileCopyPath)
    plt.imshow(obj.img)

    cv2.waitKey(20)


    plt.show()